using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Net;
using System.Diagnostics;

namespace UselessExplorer
{
    public partial class frmFtpControl : Form
    {

        clsGlobal cg = clsGlobal.Instance;

        public frmFtpControl()
        {
            InitializeComponent();
        }

        private void frmFtpControl_Load(object sender, EventArgs e)
        {
            toolStripStatusLabel1.Text = "";

            loadDirectories();
            localDirView.Drive = cbDriveList.SelectedItem.ToString();
            
        }

        private void loadDirectories()
        {
            string[] drives = Directory.GetLogicalDrives();

            foreach (string drive in drives)
            {
                cbDriveList.Items.Add(drive);
            }
            cbDriveList.SelectedItem = cbDriveList.Items[0];
        }
 
        private void loadFiles(string path, bool isRootNode)
        {
            try
            {
                this.localFileList.Items.Clear();

                string[] files = Directory.GetFiles(path);
                if (files.Length != 0)
                {
                    foreach (string file in files)
                    {
                        
                        string fileName = isRootNode ? file.Substring(path.Length) : file.Substring(path.Length + 1);
                        localFileList.Items.Add(fileName);
                        localFileList.ContextMenuStrip = ftpUploadContext;
                    }
                }
                else
                {
                    localFileList.Items.Add("No Files Found");
                }
            }
            catch (Exception ex)
            {
                localDirView.SelectedNode.Remove();
                cg.WriteLogs(Logger.LogsCategory.Exception, ex);
            }            
        }

        private void cbDriveList_SelectedIndexChanged(object sender, EventArgs e)
        {
            string val = cbDriveList.SelectedItem.ToString();
            localDirView.Drive = val.Substring(0, 2);
            localDirView.RefreshDisplay();
        }





        private void Download(string filePath, string fileName)
        {
            string ftpServerIP = tbFtpServer.Text;


            FtpWebRequest reqFTP;
            try
            {
                //filePath = <<The full path where the file is to be created. the>>,
                //fileName = <<Name of the file to be createdNeed not name on FTP server. name name()>>
                FileStream outputStream = new FileStream(filePath + "\\" + fileName, FileMode.Create);
                reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + ftpServerIP + "/" + fileName));
                reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
                reqFTP.UseBinary = true;
                reqFTP.Credentials = new NetworkCredential(tbFtpUsername.Text, tbFtpPassword.Text);
                FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
                Stream ftpStream = response.GetResponseStream();
                long cl = response.ContentLength;
                int bufferSize = 2048;
                int readCount;
                byte[] buffer = new byte[bufferSize];
                readCount = ftpStream.Read(buffer, 0, bufferSize);
                while (readCount > 0)
                {
                    outputStream.Write(buffer, 0, readCount);
                    readCount = ftpStream.Read(buffer, 0, bufferSize);
                }

                ftpStream.Close();
                outputStream.Close();
                response.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void Upload(string filename)
        {
            FileInfo fileInf = new FileInfo(filename);
            string uri = "ftp://" + tbFtpServer.Text + "/" + fileInf.Name;
            FtpWebRequest reqFTP;
            // Create FtpWebRequest object from the Uri provided
            reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + tbFtpServer.Text + "/" + fileInf.Name));
            // Provide the WebPermission Credintials
            reqFTP.Credentials = new NetworkCredential(tbFtpUsername.Text, tbFtpPassword.Text);
            // By default KeepAlive is true, where the control connection is not closed
            // after a command is executed.
            reqFTP.KeepAlive = false;
            // Specify the command to be executed.
            reqFTP.Method = WebRequestMethods.Ftp.UploadFile;
            // Specify the data transfer type.
            reqFTP.UseBinary = true;
            // Notify the server about the size of the uploaded file
            reqFTP.ContentLength = fileInf.Length;
            // The buffer size is set to 2kb
            int buffLength = 2048;
            byte[] buff = new byte[buffLength];
            int contentLen;
            // Opens a file stream (System.IO.FileStream) to read the file to be uploaded
            FileStream fs = fileInf.OpenRead();
            try
            {
                // Stream to which the file to be upload is written
                Stream strm = reqFTP.GetRequestStream();
                // Read from the file stream 2kb at a time
                contentLen = fs.Read(buff, 0, buffLength);
                // Till Stream content ends
                while (contentLen != 0)
                {
                    // Write Content from the file stream to the FTP Upload Stream
                    strm.Write(buff, 0, contentLen);
                    contentLen = fs.Read(buff, 0, buffLength);
                }

                // Close the file stream and the Request Stream
                strm.Close();
                fs.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Upload Error");
                PrintStatusMessage("Upload Error : " + ex.Message);
                cg.WriteLogs(Logger.LogsCategory.Exception, ex);
            }
        }

        public string[] GetFileList()
        {
            string[] downloadFiles;
            StringBuilder result = new StringBuilder();
            FtpWebRequest reqFTP;

            try
            {

                reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + tbFtpServer.Text + "/"));
                reqFTP.UseBinary = true;
                reqFTP.KeepAlive = false;
                reqFTP.Credentials = new NetworkCredential(tbFtpUsername.Text, tbFtpPassword.Text);
                reqFTP.Method = WebRequestMethods.Ftp.ListDirectory;
                
                FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
                StreamReader reader = new StreamReader(response.GetResponseStream());
                
                PrintStatusMessage(response.WelcomeMessage);
                PrintStatusMessage(response.StatusDescription);

                string line = reader.ReadLine();

                while (line != null)
                {
                    result.Append(line);
                    result.Append("\n");
                    line = reader.ReadLine();
                }

                toolStripStatusLabel1.Text = "Connected to " + tbFtpServer.Text;
                // to remove the trailing '\n'
                result.Remove(result.ToString().LastIndexOf('\n'), 1);
                reader.Close();
                response.Close();
                btnFtpDisconnect.Enabled = true;
                return result.ToString().Split('\n');
            }
            catch (Exception ex)
            {
                toolStripStatusLabel1.Text = "Unable to Connect to " + tbFtpServer.Text;

                cg.WriteLogs(Logger.LogsCategory.Exception, ex);
                downloadFiles = null;
                enableInputs();
                return downloadFiles;
            }
        }

        private void clearDisplayedData()
        {
            ftpFileView.DataSource = null;
            ftpDirView.Nodes.Clear();
            lbStatusMsg.Items.Clear();
        }

        private void disableInputs()
        {
            tbFtpUsername.Enabled = false;
            tbFtpPassword.Enabled = false;
            tbFtpServer.Enabled = false;
            tbFtpPort.Enabled = false;
            btnFtpConnect.Enabled = false;
        }

        private void enableInputs()
        {
            tbFtpUsername.Enabled = true;
            tbFtpPassword.Enabled = true;
            tbFtpServer.Enabled = true;
            tbFtpPort.Enabled = true;
            btnFtpConnect.Enabled = true;
            btnFtpDisconnect.Enabled = false;
        }

        private void PrintStatusMessage(string msg)
        {
            lbStatusMsg.Items.Add(msg);
        }

        private void btnFtpConnect_Click(object sender, EventArgs e)
        {
            disableInputs();
            clearDisplayedData();
            string[] files = GetFileList();

            TreeNode rootNode= new TreeNode(tbFtpServer.Text);
            ftpDirView.Nodes.Add(rootNode);
            
            if (files != null)
            {
                DataTable dt = new DataTable("Files");
                dt.Columns.Add(new DataColumn("Name"));
                dt.Columns.Add(new DataColumn("Size"));
                dt.Columns.Add(new DataColumn("Last Modified"));
               
                foreach (string file in files)
                {
                    float size = (float)((GetFileSize(file))/1024)/1024;
                    if (size != 0)
                    {
                        string timeStamp = GetTimeStamp(file);
                        dt.Rows.Add(file, size + String.Empty + "MB",timeStamp);
                    }
                    else
                    {
                        TreeNode trN = new TreeNode(file);
                        rootNode.Nodes.Add(trN);
                    }
                    
                }
                this.ftpDirView.Nodes[0].Expand();    
                ftpFileView.DataSource = dt;
            }
            else
            {
                TreeNode noItems = new TreeNode("No Items Found");
                rootNode.Nodes.Add(noItems);
            }
        }

        private string GetTimeStamp(string file)
        {
            try
            {
                FtpWebRequest req = (FtpWebRequest)WebRequest.Create("ftp://" + tbFtpServer.Text + "/" + file);
                req.Proxy = null;
                req.Credentials = new NetworkCredential(tbFtpUsername.Text, tbFtpPassword.Text);

                req.Method = WebRequestMethods.Ftp.GetDateTimestamp;

                using (FtpWebResponse resp = (FtpWebResponse)req.GetResponse())
                    return resp.LastModified.ToShortDateString();
            }
            catch (Exception ex)
            {
                cg.WriteLogs(Logger.LogsCategory.Exception, ex);
                return null;
            }
        }

        private long GetFileSize(string file)
        {
            try
            {
                FtpWebRequest req = (FtpWebRequest)WebRequest.Create("ftp://" + tbFtpServer.Text + "/" + file);
                req.Proxy = null;
                req.Credentials = new NetworkCredential(tbFtpUsername.Text, tbFtpPassword.Text);

                req.Method = WebRequestMethods.Ftp.GetFileSize;

                using (WebResponse resp = req.GetResponse())
                    return resp.ContentLength;
            }
            catch (Exception ex)
            {
                FileNotFoundException fe = new FileNotFoundException();
                if (!fe.Equals(ex))
                {
                    cg.WriteLogs(Logger.LogsCategory.Exception, ex);
                    return 0;
                }
                else
                {
                    MessageBox.Show("Got IT");
                    return 0;
                }
            }

        }

        

        private void localDirView_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            localDirView.SelectedNode = e.Node;
            string path = e.Node.FullPath;
            bool isRootNode = false;
            if (localDirView.SelectedNode.Text == cbDriveList.SelectedItem.ToString())
                isRootNode = true;
            loadFiles(path, isRootNode);
        }

        private void btnFtpDisconnect_Click(object sender, EventArgs e)
        {
            enableInputs();
            clearDisplayedData();
        }

        private void tsUpload_Click(object sender, EventArgs e)
        {
            string fileToUpload = localFileList.SelectedItems[0].Text.ToString();
            string dirPath = localDirView.SelectedNode.FullPath;
            MessageBox.Show(localDirView.SelectedNode.FullPath.Replace(@"\\\", @"\") + @"\" + fileToUpload);
            Upload(localDirView.SelectedNode.FullPath.Replace(@"\\\", @"\") + @"\" + fileToUpload);
        }

        private void localFileList_SelectedIndexChanged(object sender, EventArgs e)
        {
            FileInfo fi = new FileInfo(localDirView.SelectedNode.FullPath + @"\" + localFileList.SelectedItems[0].Text.ToString());
            localFileList.DoDragDrop(fi, DragDropEffects.None);
        }

        private void localFileList_DragLeave(object sender, EventArgs e)
        {
            MessageBox.Show("Drag Out");
        }

   
    }
}